/*
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

/*
 *
 *
 *
 *
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

package own.stu.jobgib.playown.juc.completeFuture.own;

import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.BiFunction;
import java.util.concurrent.Executor;

public interface MyCompletionStage<T> {

    <U> MyCompletionStage<U> thenApply(Function<? super T, ? extends U> fn);

    <U> MyCompletionStage<U> thenApplyAsync
            (Function<? super T, ? extends U> fn);

    <U> MyCompletionStage<U> thenApplyAsync
            (Function<? super T, ? extends U> fn,
             Executor executor);

    MyCompletionStage<Void> thenAccept(Consumer<? super T> action);

    MyCompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);

    MyCompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,
                                                 Executor executor);

    MyCompletionStage<Void> thenRun(Runnable action);

    MyCompletionStage<Void> thenRunAsync(Runnable action);

    MyCompletionStage<Void> thenRunAsync(Runnable action,
                                              Executor executor);

    <U, V> MyCompletionStage<V> thenCombine
            (MyCompletionStage<? extends U> other,
             BiFunction<? super T, ? super U, ? extends V> fn);

    <U, V> MyCompletionStage<V> thenCombineAsync
            (MyCompletionStage<? extends U> other,
             BiFunction<? super T, ? super U, ? extends V> fn);

    <U, V> MyCompletionStage<V> thenCombineAsync
            (MyCompletionStage<? extends U> other,
             BiFunction<? super T, ? super U, ? extends V> fn,
             Executor executor);

    <U> MyCompletionStage<Void> thenAcceptBoth
            (MyCompletionStage<? extends U> other,
             BiConsumer<? super T, ? super U> action);

    <U> MyCompletionStage<Void> thenAcceptBothAsync
            (MyCompletionStage<? extends U> other,
             BiConsumer<? super T, ? super U> action);

    <U> MyCompletionStage<Void> thenAcceptBothAsync
            (MyCompletionStage<? extends U> other,
             BiConsumer<? super T, ? super U> action,
             Executor executor);

    MyCompletionStage<Void> runAfterBoth(MyCompletionStage<?> other,
                                              Runnable action);

    MyCompletionStage<Void> runAfterBothAsync(MyCompletionStage<?> other,
                                                   Runnable action);

    /**
     * Returns a new MyCompletionStage that, when this and the other
     * given stage complete normally, executes the given action using
     * the supplied executor.
     * <p>
     * See the {@link MyCompletionStage} documentation for rules
     * covering exceptional completion.
     *
     * @param other    the other MyCompletionStage
     * @param action   the action to perform before completing the
     *                 returned MyCompletionStage
     * @param executor the executor to use for asynchronous execution
     * @return the new MyCompletionStage
     */
    MyCompletionStage<Void> runAfterBothAsync(MyCompletionStage<?> other,
                                                   Runnable action,
                                                   Executor executor);

    <U> MyCompletionStage<U> applyToEither
            (MyCompletionStage<? extends T> other,
             Function<? super T, U> fn);

    <U> MyCompletionStage<U> applyToEitherAsync
            (MyCompletionStage<? extends T> other,
             Function<? super T, U> fn);

    <U> MyCompletionStage<U> applyToEitherAsync
            (MyCompletionStage<? extends T> other,
             Function<? super T, U> fn,
             Executor executor);

    MyCompletionStage<Void> acceptEither
            (MyCompletionStage<? extends T> other,
             Consumer<? super T> action);

    MyCompletionStage<Void> acceptEitherAsync
            (MyCompletionStage<? extends T> other,
             Consumer<? super T> action);

    MyCompletionStage<Void> acceptEitherAsync
            (MyCompletionStage<? extends T> other,
             Consumer<? super T> action,
             Executor executor);

    MyCompletionStage<Void> runAfterEither(MyCompletionStage<?> other,
                                                Runnable action);

    MyCompletionStage<Void> runAfterEitherAsync
            (MyCompletionStage<?> other,
             Runnable action);

    MyCompletionStage<Void> runAfterEitherAsync
            (MyCompletionStage<?> other,
             Runnable action,
             Executor executor);

    <U> MyCompletionStage<U> thenCompose
            (Function<? super T, ? extends MyCompletionStage<U>> fn);

    <U> MyCompletionStage<U> thenComposeAsync
            (Function<? super T, ? extends MyCompletionStage<U>> fn);

    <U> MyCompletionStage<U> thenComposeAsync
            (Function<? super T, ? extends MyCompletionStage<U>> fn,
             Executor executor);

    MyCompletionStage<T> exceptionally
            (Function<Throwable, ? extends T> fn);

    MyCompletionStage<T> whenComplete
            (BiConsumer<? super T, ? super Throwable> action);

    MyCompletionStage<T> whenCompleteAsync
            (BiConsumer<? super T, ? super Throwable> action);

    MyCompletionStage<T> whenCompleteAsync
            (BiConsumer<? super T, ? super Throwable> action,
             Executor executor);

    <U> MyCompletionStage<U> handle
            (BiFunction<? super T, Throwable, ? extends U> fn);

    <U> MyCompletionStage<U> handleAsync
            (BiFunction<? super T, Throwable, ? extends U> fn);

    <U> MyCompletionStage<U> handleAsync
            (BiFunction<? super T, Throwable, ? extends U> fn,
             Executor executor);

    MyCompletableFuture<T> toCompletableFuture();

}
